import {
  ConditionOption,
  Match,
  Option,
  OptionCondition,
  WebMatch,
  WebOption,
} from '../type';
import { event } from './event';

export type Row = {
  parent_option_name?: string;
  option_name: string;
  website_code: string;
  image_url?: string;
  options: WebOption[];
  rowSpan?: number;
  category_name: string;
  condition_name: string;
  isEdit?: boolean;
  alias_name: string;
};

const enum Status {
  New,
  Modify,
}

const oldValue = ref('');
let tempId = '';

export const getMatchKey = (row: {
  website_code: string;
  category_name: string;
  alias_name: string;
  condition_name: string;
}) => {
  const { website_code, category_name, alias_name, condition_name } = row;
  return `${website_code}-${category_name}-${condition_name}-${alias_name}`;
};

export const getOptionKey = ({
  website_code,
  category_name,
  condition_name,
  alias_name,
  option_value,
}: {
  website_code: string;
  category_name: string;
  condition_name: string;
  alias_name: string;
  option_value: string;
}) => {
  return `${website_code}-${category_name}-${condition_name}-${alias_name}-${option_value}`;
};

export const genOptionKey = (record: {
  alias_name?: string;
  option_name: string;
}) => record.alias_name || record.option_name;
class OptionTable {
  // rows: ConditionOption[];
  data: OptionCondition;
  status: Status = Status.Modify;
  constructor(data: OptionCondition) {
    this.data = data;
  }

  get rows() {
    return this.data.options;
  }

  get getMap() {
    const matchMap: Map<string, Match> = new Map();
    const optionMap: Map<string, Option> = new Map();
    const conditionMap: Map<string, ConditionOption> = new Map();
    this.rows.forEach(item => {
      const _option_name = genOptionKey(item);
      conditionMap.set(_option_name, item);
      item.matches.forEach(match => {
        const matchKey = getMatchKey({
          alias_name: item.alias_name || item.option_name,
          website_code: match.website_code,
          category_name: match.category_name,
          condition_name: match.condition_name,
        });
        matchMap.set(matchKey, match);
        match.options.forEach(option => {
          const optionKey = getOptionKey({
            ...option,
            alias_name: option.option_name,
          });
          optionMap.set(optionKey, option);
        });
      });
    });
    return {
      matchMap,
      optionMap,
      conditionMap,
    };
  }

  get tableData() {
    const list: Row[] = [];
    this.rows.forEach(item => {
      if (item.matches.length) {
        item.matches.forEach((match, index) => {
          list.push({
            rowSpan: index == 0 ? item.matches.length : 0,
            options: match.options,
            website_code: match.website_code,
            option_name: item.option_name,
            condition_name: match.condition_name,
            category_name: match.category_name,
            image_url: item.image_url,
            isEdit: item.isEdit,
            alias_name: genOptionKey(item),
          });
        });
      } else {
        list.push({
          options: [],
          website_code: '',
          option_name: item.option_name,
          alias_name: genOptionKey(item),
          category_name: '',
          condition_name: '',
          image_url: item.image_url,
          isEdit: item.isEdit,
        });
      }
    });
    return list;
  }

  // 生成新选项
  addNew(row: WebMatch) {
    const [option] = row.options;
    const { matchMap, optionMap, conditionMap } = this.getMap;
    const matchKey = getMatchKey({
      alias_name: row.options[0].option_name ?? '',
      category_name: row.category_name,
      website_code: row.website_code,
      condition_name: row.condition_name,
    });
    const optionKey = genOptionKey(option);
    if (!conditionMap.has(optionKey)) {
      // 选项不存在直接添加
      this.rows.unshift({
        option_name: option.option_name,
        alias_name: option.option_name,
        image_url: option.image_url,
        matches: [row],
      });
      event.emit('modify');
    } else {
      // 选项存在
      const _option = conditionMap.get(optionKey);
      if (_option) {
        if (matchMap.has(matchKey)) {
          // 是否同一匹配站点条件
          const match = matchMap.get(matchKey);
          if (match) {
            // 判断匹配条件中选项是否相同
            const _key = getOptionKey({
              ...option,
              alias_name: option.option_name,
            });
            if (optionMap.has(_key)) {
              // 存在相同选项
              console.warn('已存在:' + option.option_name);
            } else {
              // 一般不会存在这种情况
              match.options.push(option);
              event.emit('modify');
            }
          }
        } else {
          // 不是同一站点直接添加
          _option.matches.push(row);
          event.emit('modify');
        }
      }
    }
  }

  removeOption(row: Row, option: WebOption) {
    const { matchMap } = this.getMap;
    const match = matchMap.get(getMatchKey(row));
    if (match) {
      match.options = match.options.filter(
        item => item.option_value != option.option_value
      );
      event.emit('remove');
    }
  }

  removeAll(row: Row) {
    const { matchMap } = this.getMap;
    const match = matchMap.get(getMatchKey(row));
    if (match) {
      match.options = [];
      event.emit('remove');
    }
  }

  removeRow(row: Row) {
    const { matchMap, conditionMap } = this.getMap;
    const option = conditionMap.get(row.alias_name);
    if (option) {
      if (option.matches.length <= 1) {
        this.data.options = this.data.options.filter(
          item => item.option_name != row.option_name
        );
        event.emit('remove');
      } else {
        const match = matchMap.get(getMatchKey(row));
        option.matches = option.matches.filter(item => item != match);
      }
      event.emit('remove');
    }
  }

  // 关联选项
  addMerge(option_name: string, row: WebMatch) {
    const { matchMap, conditionMap } = this.getMap;
    const option = conditionMap.get(option_name);
    if (option) {
      // 检测是否同一站点
      const find = option.matches.find(item =>
        compare(item, row, [
          'category_name',
          'category_code',
          'website_code',
          'condition_name',
        ])
      );
      if (find) {
        if (
          find.options.some(item =>
            compare(item, row.options[0], [
              'option_code',
              'option_name',
              'option_value',
            ])
          )
        )
          return;
        find.options.push(row.options[0]);
        event.emit('modify');
      } else {
        option.matches.push(row);
        event.emit('modify');
      }
      return;
    }

    const match = matchMap.get(option_name);
    if (match) {
      match.options.push(row.options[0]);
      event.emit('modify');
    }
  }

  // 点击新增
  addOption(inputRef: Ref<HTMLElement | undefined>) {
    this.status = Status.New;
    tempId = generateUUID();
    this.data.options.unshift({
      option_name: tempId,
      alias_name: '',
      image_url: '',
      matches: [],
      isEdit: true,
    });
    nextTick(() => {
      inputRef?.value?.focus();
    });
  }

  save(option_name: string, inputRef: Ref<HTMLElement | undefined>) {
    // if (!option_name) {
    //   message.warn('选项名不能为空');
    //   inputRef.value?.focus();
    //   return;
    // }
    if (this.status == Status.New) {
      this.saveNew(option_name, inputRef);
    } else if (this.status == Status.Modify) {
      this.saveModify(option_name);
    }
  }

  saveNew(option_name: string, _inputRef: Ref<HTMLElement | undefined>) {
    const { conditionMap } = this.getMap;
    const isRepeat = conditionMap.get(option_name);
    if (!option_name || conditionMap.get(option_name)) {
      this.data.options = this.data.options.filter(
        item => item.option_name != tempId
      );
      tempId = '';
      if (isRepeat) {
        message.warn(`选项${option_name}已存在`);
      }
      return;
    }
    const condition = conditionMap.get(tempId);
    if (condition) {
      condition.alias_name = option_name;
      condition.isEdit = false;
      event.emit('modify');
      oldValue.value = '';
    }
  }

  saveModify(option_name: string) {
    const { conditionMap } = this.getMap;
    const option = conditionMap.get(oldValue.value);
    const isRepeat = conditionMap.get(option_name);
    if (option) {
      if (isRepeat && option_name != oldValue.value) {
        message.warn(`选项${option_name}已存在`);
      } else if (option_name) {
        option.alias_name = option_name;
      }
      option.isEdit = false;
      event.emit('modify');
    }
  }

  saveImage(option_name: string, image_url: string) {
    const { conditionMap } = this.getMap;
    const condition = conditionMap.get(option_name);
    if (condition) {
      condition.image_url = image_url;
      event.emit('modify');
    }
  }

  modifyOption(
    option_name: string,
    inputRef: Ref<HTMLElement | undefined>,
    tempValue: Ref<string>
  ) {
    this.status = Status.Modify;
    const { conditionMap } = this.getMap;
    const condition = conditionMap.get(option_name);
    if (condition) {
      oldValue.value = option_name;
      condition.isEdit = true;
      tempValue.value = condition.alias_name || condition.option_name;
      nextTick(() => {
        inputRef.value?.focus();
      });
    }
  }
}

export default OptionTable;
